using System;
using System.Configuration;

using Google.Apps.Provisioning.Authentication;

namespace Google.Apps.Provisioning
{
    /// <summary>
    /// GoogleAppsProvisioning provides a single point of entry to all commonly used classes in the Google.Apps.Provisioning
    /// namespace.  Any consumers of this library should be able to use this facade without needing to look at
    /// any other subsystems in the API.  All commonly used functionality for a typical consumer (such as a web
    /// site) are included in this facade. <p/>
    /// To use the facade, certain application config variables are required.  Once these are setup, a caller
    /// can create an instance of the facade and begin making API calls with no other initialization work
    /// required.  See the <see cref="GoogleAppsProvisioning()"/> default constructor for information on setting up 
    /// the application config variables.<p/>
    /// For web applications, it is recommended that a single instance of
    /// the facade is used per web site.  This is because the SecurityToken issued by Google is valid for 24
    /// hours, and this facade has built in support for refreshing the token when necessary.
    /// </summary>
    public class GoogleAppsProvisioning
    {
        private string domain;

        private AuthenticationToken securityToken;
        private ProvisioningManager provisioningManager;

        /// <summary>
        /// The authentication token that is currently being used by the facade.  This token will be
        /// automatically created when the facade's constructor is called.
        /// </summary>
        public AuthenticationToken AuthenticationToken
        {
            get { return securityToken; }
        }

        /// <summary>
        /// The Google Apps domain that is currently being used by the facade.
        /// </summary>
        public string Domain
        {
            get { return domain; }
        }

        /// <summary>
        /// Initializes the class using default values from the application's config file (eg, web.config).
        /// After initialization, all API methods are ready for use.<p/>
        /// The following config file entries are required:<br/>
        /// <li/>Google.Apps.Provisioning.Domain - The domain of the Google Apps instance, eg "example.com".
        /// <li/>Google.Apps.Provisioning.AdminEmail - The email address of an account on the Google Apps domain that has
        /// admin rights.  This account will be used for logging into the provisioning API.
        /// <li/>Google.Apps.Provisioning.AdminPassword - The password for the admin account.
        /// Sample config file:
        /// <code>
        ///   &lt;add key="Google.Apps.Provisioning.AdminEmail" value="admin@example.com" /&gt;
        ///   &lt;add key="Google.Apps.Provisioning.AdminPassword" value="passwd" /&gt;
        ///   &lt;add key="Google.Apps.Provisioning.Domain" value="example.com" /&gt;
        /// </code>
        /// </summary>
        public GoogleAppsProvisioning()
        {
            string domain = 
                ConfigurationSettings.AppSettings[ "Google.Apps.Provisioning.Domain" ];

            string adminEmail = 
                ConfigurationSettings.AppSettings[ "Google.Apps.Provisioning.AdminEmail" ];
            
            string adminPassword = 
                ConfigurationSettings.AppSettings[ "Google.Apps.Provisioning.AdminPassword" ];

            Initialize( domain, adminEmail, adminPassword );
        }

        /// <summary>
        /// Initializes the facade using configuration values provided by the caller.  This constructor
        /// is provided as an alternative for callers who do not want to store their domain and admin
        /// account information in a config file.
        /// </summary>
        /// <param name="domain">The domain of the Google Apps instance, eg "example.com".</param>
        /// <param name="adminEmail">The email address of an account on the Google Apps domain that has
        /// admin rights.  This account will be used for logging into the provisioning API.</param>
        /// <param name="adminPassword">The password for the admin account.</param>
        public GoogleAppsProvisioning( string domain, string adminEmail, string adminPassword )
        {
            Initialize( domain, adminEmail, adminPassword );
        }

        private void Initialize( string domain, string adminEmail, string adminPassword )
        {
            this.domain = domain;
            
            securityToken = 
                new AuthenticationToken( adminEmail, adminPassword );

            provisioningManager = 
                new ProvisioningManager( this.domain, securityToken );
        }

        /// <summary>
        /// Create a user (hosted email account) using Google's Provisioning API.
        /// </summary>
        /// <param name="userName">The username for the account.  This username must be unique.</param>
        /// <param name="password">Password for the account.</param>
        /// <param name="firstName">The first name of the user.</param>
        /// <param name="lastName">The last name of the user.</param>
        /// <param name="quota">The quota (storage space) allowed for the user's email account, in megabytes.</param>
        /// <returns></returns>
        public ProvisioningResponse CreateUser( 
            string userName, string password, string firstName, string lastName, int quota )
        {
            return provisioningManager.CreateUser( userName, password, firstName, lastName, quota );
        }

        /// <summary>
        /// Permanently delete a user using Google's Provisioning API.
        /// </summary>
        /// <param name="userName">The username of the account to delete.</param>
        /// <returns></returns>
        public ProvisioningResponse DeleteUser( string userName )
        {
            return provisioningManager.DeleteUser( userName );
        }

        /// <summary>
        /// Retrieves account information for a user using Google's Provisioning API.
        /// </summary>
        /// <param name="userName">The username to retrieve information for.</param>
        /// <param name="user">Out parameter populated with the retrieved information.</param>
        public ProvisioningResponse RetrieveUser( string userName, out GoogleUser user )
        {
            return provisioningManager.RetrieveUser( userName, out user );
        }

        /// <summary>
        /// Update a user using Google's Provisioning API.  Note that the username cannot 
        /// be updated.
        /// </summary>
        /// <param name="userName">The username for the account.</param>
        /// <param name="password">Password for the account.</param>
        /// <param name="firstName">The first name of the user.</param>
        /// <param name="lastName">The last name of the user.</param>
        /// <returns></returns>
        public ProvisioningResponse UpdateUser( 
            string userName, string password, string firstName, string lastName )
        {
            return provisioningManager.UpdateUser( userName, password, firstName, lastName );
        }
    }
}
